home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Magazine / C_Tutorial / Part-6 / IFF-library / ShowIFF / ShowIFF.c < prev    next >
C/C++ Source or Header  |  1993-05-24  |  35KB  |  1,506 lines

  1. /*
  2. **
  3. **    $Id: ShowIFF.c,v 3.5 93/05/24 15:34:36 chris Exp $
  4. **    $Revision: 3.5 $
  5. **
  6. **    $Filename: ShowIFF/ShowIFF.c $
  7. **    $Author: Christian A. Weber $
  8. **    $Release: 23.2 $
  9. **    $Date: 93/05/24 15:34:36 $
  10. **
  11. **  NAME
  12. **        ShowIFF - a fast IFF picture viewer for Workbench and Shell
  13. **
  14. **        >>>> For full documentation, see ShowIFF.doc <<<<
  15. **
  16. **  DESCRIPTION
  17. **        ShowIFF can display any Amiga IFF pictures with up to 24 bitplanes
  18. **        (24 bit pictures are displayed in "true color" with max. colors).
  19. **        All known formats (HAM, HAM8, Halfbrite) and all display modes
  20. **        like NTSC, PAL, VGA, A2024, ... are supported.
  21. **        If a picture is larger than the screen, you can use the mouse to
  22. **        scroll around.
  23. **        ShowIFF can be used from Workbench or Shell, it can create an
  24. **        AppIcon. It can display single files or whole drawers or disks.
  25. **
  26. **  REQUIREMENTS
  27. **        - iff.library V22+
  28. **        - Amiga OS 2.0 or newer (3.0 for AGA modes)
  29. **        - Original, Enhanced or AGA chipset
  30. **        - to compile: SAS/C compiler V6
  31. **
  32. **  AUTHOR
  33. **        Christian A. Weber
  34. **
  35. **        Internet:    weber@amiga.physik.unizh.ch
  36. **        UUCP:        chris@mighty.adsp.sub.org
  37. **        Snail mail:  Bruggerweg 2, CH-8037 Zürich, Switzerland.
  38. **
  39. **        Suggestions, bug reports or donations are welcome.
  40. **
  41. **  LEGAL STUFF
  42. **        COPYRIGHT (C) 1987-1993 BY CHRISTIAN A. WEBER. ALL RIGHTS RESERVED.
  43. **        THIS PROGRAM MAY BE DISTRIBUTED FOR NON PROFIT PURPOSES ONLY.
  44. **        NO WARRANTY. USE AT YOUR OWN RISK.
  45. **
  46. **  HISTORY
  47. **
  48. **    15-Oct-87  CHW  V1.0   Created this file!
  49. **    30-Jun-88  CHW  V1.4   Directory scan fixed for FFS, cleaned up
  50. **    16-Nov-88  CHW  V1.5   Overscan implemented
  51. **    28-Nov-88  CHW  V1.6   Minimal screen size is now 64x64 pixels
  52. **    02-Jan-89  CHW  V1.7   Double-buffering implemented
  53. **    25-Sep-89  CHW  V2.01  Changed to Lattice C and ARP library
  54. **    27-Sep-89  CHW  V2.02  Screen scrolling implemented
  55. **    22-Nov-89  CHW  V2.03  Rejects Non-ILBM files correctly
  56. **    21-Feb-90  CHW  V2.04  'NoMemForGfx' bug fixed, overscan fixed
  57. **    28-Feb-90  CHW  V2.10  SHAM support code added
  58. **    14-Mar-90  CHW  V2.11  Memory fragmentation workaround, cleanup
  59. **    08-Apr-90  CHW  V2.12  Pics with more than 6 planes don't guru
  60. **    22-Apr-90  CHW  V2.14  New startup code, WB cleanup works now.
  61. **    16-Jul-90  CHW  V2.15  Works now properly with MoreRows & OS 2.0
  62. **    16-Sep-90  CHW  V2.16  Scrolling SHAM pictures implemented
  63. **    03-Oct-90  CHW  V2.17  MaxX0 divided by 2 because of a 2.0 bug
  64. **    30-Oct-90  MAB  V2.20  ShowIFF can be turned into an appicon
  65. **    11-Jan-91  CHW  V2.21  SHAM color errors fixed
  66. **    11-Jan-91  CHW  V2.22  AppIcon image/pos are taken from .info file
  67. **    13-Jan-91  CHW  V2.23  COMMAND mode added, overscan bug fixed (?)
  68. **    14-Jan-91  CHW  V2.24  Icon tooltypes added, code moved around
  69. **    24-Jan-91  CHW  V2.25  Minor bug fixes
  70. **    03-May-91  CHW  V2.26  Vertical centering and NOCENTER option added
  71. **    23-May-91  CHW  V2.27  Pointer option added
  72. **    27-May-91  CHW  V2.28  True Color Table fixed and extended
  73. **    23-Jun-91  CHW  V2.29  AppIcon's image can be specified (ICON=...)
  74. **    23-Apr-92  CHW  V2.30  RasInfo-bug workaround only under V36-38
  75. **    29-Jul-92  CHW  V2.31  Compiles with new IFF includes, 8 bitplanes
  76. **    15-Oct-92  SG   V3.00  New display code, true AGA support
  77. **    01-Dec-92  CHW  V3.1   ARP support removed, substancial rewrite
  78. **    04-Feb-92  CHW  V3.4   Bug in ScrollRaster() call removed (would crop)
  79. */
  80.  
  81. // #define VERBOSE
  82.  
  83. #include <hardware/custom.h>        /* For SHAM/DYNA support ONLY */
  84. #include <proto/exec.h>
  85. #include <exec/memory.h>
  86. #include <exec/execbase.h>
  87. #include <proto/utility.h>
  88. #include <utility/utility.h>
  89. #include <proto/graphics.h>
  90. #include <graphics/gfxbase.h>
  91. #include <graphics/gfxmacros.h>
  92. #include <graphics/displayinfo.h>
  93. #include <proto/intuition.h>
  94. #include <intuition/intuitionbase.h>
  95. #include <proto/icon.h>
  96. #include <workbench/icon.h>
  97. #include <proto/wb.h>
  98. #include <workbench/startup.h>
  99. #include <proto/dos.h>
  100.  
  101. #include <string.h>
  102. #include <stdlib.h>
  103.  
  104. #include <libraries/iff.h>
  105.  
  106. #include "showiff_rev.h"
  107.  
  108.  
  109. /****************************************************************************
  110. **    Some useful macros
  111. */
  112.  
  113. #define MAX(a,b)        ((a)>(b)?(a):(b))
  114. #define OSVERSION(ver)    (IntuitionBase->LibNode.lib_Version >= (ver))
  115. #define HAS_AGA            (GfxBase->ChipRevBits0 & GFXF_AA_ALICE)
  116.  
  117. #define PICF_DYNA        1
  118.  
  119. #define MAXCOLORS        256
  120.  
  121. #define XOSCAN            0    /* Scroll if picture is bigger than screen + XOSCAN */
  122. #define YOSCAN            16    /* Scroll if picture is bigger than screen + YOSCAN */
  123.  
  124.  
  125. /****************************************************************************
  126. **    Stuctures
  127. */
  128.  
  129. typedef struct
  130. {
  131.     UBYTE    R, G, B;        /* Red, Green, Blue values (0..255) */
  132. } RGBColor;
  133.  
  134.  
  135. struct Picture
  136. {
  137.     struct Screen    *Screen;            /* The picture's screen */
  138.     struct Window    *Window;            /* Window for mouse handling */
  139.     struct BitMap    *BitMap;            /* BitMap, can be larger than screen */
  140.     UWORD            *SHAMColors;        /* SHAM color table array or NULL */
  141.     WORD            Y0;                    /* Y of picture relative to screen */
  142.     UWORD            PicW, PicH;            /* Total image dimensions */
  143.     UWORD            ColorCount;            /* # of colors in color palette */
  144.     RGBColor        Palette[MAXCOLORS];    /* The picture's color palette */
  145.     UBYTE            Flags;                /* See PICF_... */
  146. };
  147.  
  148. struct SHAMChunk
  149. {
  150.     struct IFFL_Chunk    Chunk;
  151.     UWORD                Version;
  152.     UWORD                Colors[1];        /* open array */
  153. };
  154.  
  155.  
  156. /****************************************************************************
  157. **    Tooltypes and other constant strings
  158. */
  159.  
  160. #define OPTIONSTOOLTYPE        "OPTIONS"
  161. #define ICONTOOLTYPE        "ICON"
  162. #define XPOSTOOLTYPE        "ICONXPOS"
  163. #define YPOSTOOLTYPE        "ICONYPOS"
  164. #define ICONNAMETOOLTYPE    "ICONNAME"
  165. #define APPICONPORTNAME        "ShowIFF-AppIcon"
  166. #define DEFAULTAPPICONNAME    "IFF Picture Viewer"
  167.  
  168.  
  169. /****************************************************************************
  170. **    External references
  171. */
  172.  
  173. extern struct Process *ProcessBase;        /* Pointer to our process */
  174. extern struct Custom __far custom;        /* For SHAM/DYNA copper list */
  175.  
  176.  
  177. /****************************************************************************
  178. **    Global variables
  179. */
  180.  
  181. struct Library            *UtilityBase, *IconBase, *WorkbenchBase;
  182. struct GfxBase            *GfxBase;
  183. struct IntuitionBase    *IntuitionBase;
  184. struct Library            *IFFBase;        /* Nothing goes without that */
  185.  
  186. struct DiskObject    *dobj;                /* Our icon */
  187. IFFL_HANDLE            ifffile;            /* IFF file handle */
  188. struct Picture        pic1, pic2;            /* 2 pictures for double buffering */
  189. BPTR                wbwindow;            /* Output window for Workbench mode */
  190. BPTR                oldcos;                /* Old output file handle */
  191. LONG                delay = 0x7fffffff;    /* Time (in jiffies) for each picture */
  192. LONG                monitorid;            /* Monitor ID or 0 if no specific monitor */
  193.  
  194. WORD __chip            emptysprite[8];        /* ShowIFF's mouse pointer sprite */
  195.  
  196.  
  197. static char VersionString[] =
  198.     VERSTAG " by Christian A. Weber and Peter W. Simeon\n\r";
  199.  
  200. static char WindowTitle[] =
  201.     "CON:10/24/600/92/" VERS " (" DATE ")/AUTO/CLOSE";
  202.  
  203. char StdWindowName[] = "NIL:";    /* Default Workbench window name */
  204.  
  205.  
  206. /*
  207. **    CLI_Template and argv are used for ArgsStartup20.o. Argv receives the
  208. **    arguments from a ReadArgs() call in the startup code. CLI_Help will
  209. **    be printed if no arguments are specified on the command line.
  210. */
  211.  
  212. char CLI_Template[] =
  213.     "Patterns/M,ALL/S,D=DELAY/N,L=LOOP/S,MONITOR/K,NB=NOBREAK/S,NOCENTER/S,"
  214.     "NO=NOOVERSCAN/S,POINTER/S,CMD=COMMAND/K";
  215.  
  216. static char CLI_Help[] =
  217.     "Usage: ShowIFF [files or patterns] [ALL] [DELAY delay] [LOOP] [MONITOR id]\n"
  218.     "\t[NOBREAK] [NOCENTER] [NOOVERSCAN] [POINTER] [COMMAND \"Command %s args\"]\n";
  219.  
  220. struct
  221. {
  222.     char    **Patterns;
  223.     LONG    AllFlag;
  224.     LONG    *DelayPtr;
  225.     LONG    LoopFlag;
  226.     char    *Monitor;
  227.     LONG    NoBreakFlag;
  228.     LONG    NoCenterFlag;
  229.     LONG    NoOverscanFlag;
  230.     LONG    PointerFlag;
  231.     char    *Command;
  232. } argv;
  233.  
  234.  
  235. /****************************************************************************
  236. **    Make sure a value is between two borders
  237. */
  238.  
  239. LONG SetBounds(LONG is, LONG min, LONG max)
  240. {
  241.     if (is > max) is = max;
  242.     if (is < min) is = min;
  243.     return is;
  244. }
  245.  
  246.  
  247. /****************************************************************************
  248. **    Get a positive number in hex ($1234 or 0x1234) or decimal
  249. */
  250.  
  251. static ULONG GetNumber(char *string)
  252. {
  253.     ULONG Atoi(char *), Atox(char *);
  254.  
  255.     if ((string[0] == '0') && (string[1] == 'x'))
  256.     {
  257.         string++;
  258.         goto hex;
  259.     }
  260.     else if (string[0] == '$')
  261.     {
  262. hex:
  263.         string++;
  264.         return Atox(string);
  265.     }
  266.     else return Atoi(string);
  267. }
  268.  
  269.  
  270. /***************************************************************************
  271. **    Get the secondary error from iff.library and display an error text
  272. */
  273.  
  274. static void PrintIFFError(void)
  275. {
  276.     char *text;
  277.  
  278.     switch (IFFL_IFFError() )
  279.     {
  280.         case IFFL_ERROR_OPEN:
  281.             text = "Can't open file";
  282.             break;
  283.  
  284.         case IFFL_ERROR_READ:
  285.             text = "Error reading file";
  286.             break;
  287.  
  288.         case IFFL_ERROR_NOMEM:
  289.             text = "Not enough memory";
  290.             break;
  291.  
  292.         case IFFL_ERROR_NOTIFF:
  293.             text = "Not an IFF file";
  294.             break;
  295.  
  296.         case IFFL_ERROR_NOBMHD:
  297.             text = "No IFF BMHD found";
  298.             break;
  299.  
  300.         case IFFL_ERROR_NOBODY:
  301.             text = "No IFF BODY found";
  302.             break;
  303.  
  304.         case IFFL_ERROR_BADCOMPRESSION:
  305.             text = "Unsupported compression mode";
  306.             break;
  307.  
  308.         default:
  309.             text = "Unspecified error";
  310.             break;
  311.     }
  312.  
  313.     Printf("%s\n", text);
  314. }
  315.  
  316.  
  317. /***************************************************************************
  318. **    V37 replacement for FreeBitMap()
  319. */
  320.  
  321. void MyFreeBitMap(struct BitMap *bm)
  322. {
  323.     if (OSVERSION(39) )
  324.     {
  325.         FreeBitMap(bm);
  326.     }
  327.     else                    /* Running under V37 */
  328.     {
  329.         LONG    planesize = bm->BytesPerRow * bm->Rows;
  330.         int        i;
  331.  
  332.         for (i = 0; i < bm->Depth; ++i)
  333.         {
  334.             if (bm->Planes[i])
  335.             {
  336.                 FreeMem(bm->Planes[i], planesize);
  337.             }
  338.         }
  339.         FreeVec(bm);
  340.     }
  341. }
  342.  
  343.  
  344. /***************************************************************************
  345. **    Allocate a BitMap structure and allocate CHIP memory for the planes.
  346. */
  347.  
  348. struct BitMap *MyAllocBitMap(LONG depth, LONG width, LONG height)
  349. {
  350.     struct BitMap *bm;
  351.  
  352.     if (OSVERSION(39) )
  353.     {
  354.         bm = AllocBitMap(width, height, depth, BMF_CLEAR | BMF_DISPLAYABLE, NULL);
  355.     }
  356.     else
  357.     {
  358.         LONG planesize, bmsize = sizeof(struct BitMap);
  359.  
  360.         /*
  361.         **    If the bitmap has more than 8 planes, we add the size of the
  362.         **    additional plane pointers to the amount of memory we allocate
  363.         **    for the bitmap structure.
  364.         */
  365.         if (depth > 8)
  366.             bmsize += sizeof(PLANEPTR) * (depth-8);
  367.  
  368.         if (bm = AllocVec(bmsize, MEMF_PUBLIC | MEMF_CLEAR) )
  369.         {
  370.             int i;
  371.  
  372.             InitBitMap(bm, depth, width, height);
  373.             planesize = bm->BytesPerRow * bm->Rows;
  374.  
  375.             for (i = 0; i < depth; ++i)
  376.             {
  377.                 if (bm->Planes[i] = AllocMem(planesize, MEMF_CHIP | MEMF_CLEAR) )
  378.                 {
  379.                 }
  380.                 else
  381.                 {
  382.                     MyFreeBitMap(bm);
  383.                     bm = NULL;
  384.                     break;
  385.                 }
  386.             }
  387.         }
  388.     }
  389.  
  390.     return bm;
  391. }
  392.  
  393.  
  394. /****************************************************************************
  395. **    Load a color palette (24 bit resolution)
  396. */
  397.  
  398. static void LoadRGB8(struct ViewPort *vp, RGBColor *color, int count)
  399. {
  400.     int i;
  401.  
  402.     for (i=0; i < count; ++color, ++i)
  403.     {
  404.         if (OSVERSION(39) )
  405.         {
  406.             SetRGB32(vp, i, color->R<<24, color->G<<24, color->B<<24);
  407.         }
  408.         else
  409.         {
  410.             SetRGB4(vp, i, color->R>>4, color->G>>4, color->B>>4);
  411.         }
  412.     }
  413. }
  414.  
  415.  
  416. /****************************************************************************
  417. **    Create a truecolor 24bit palette with <1 << totalbits> entries.
  418. **    The bitplanes will have the order G6G7R7B7 or G4G5G6G7R6R7B6B7 ...
  419. **                              Plane#: 0 1 2 3     0 1 2 3 4 5 6 7
  420. **    The result is the number of green planes (red and blue have always the
  421. **    same number and can be calculated as (totalbits-greenbits)/2).
  422. */
  423.  
  424. static int CreateTrueColorPalette(RGBColor *palette, int totalbits)
  425. {
  426.     int numcolors, i, rbits, gbits, bbits, rlevels, glevels, blevels;
  427.  
  428.     numcolors = 1 << totalbits;
  429.  
  430.     /*
  431.     **    Divide the total number of bits into the bits for r/g/b. Green is
  432.     **    the most important color, so it gets the remaining bits as well.
  433.     */
  434.     rbits = gbits = bbits = totalbits / 3;
  435.     gbits += totalbits % 3;
  436.  
  437.     rlevels = 1 << rbits;
  438.     glevels = 1 << gbits;
  439.     blevels = 1 << bbits;
  440.  
  441.     for (i=0; i<numcolors; ++palette, ++i)
  442.     {
  443.         palette->G = (( i                   % glevels) * 0xFF) / (glevels-1);
  444.         palette->R = (((i >>  gbits)        % rlevels) * 0xFF) / (rlevels-1);
  445.         palette->B = (((i >> (gbits+rbits)) % blevels) * 0xFF) / (blevels-1);
  446.     }
  447.  
  448.     return gbits;
  449. }
  450.  
  451.  
  452. /****************************************************************************
  453. **    Create intermediate SHAM copper list if this is an SHAM picture.
  454. **    This feature will probably be removed; with AGA it's useless anyway.
  455. */
  456.  
  457. void MakeSHAMCopList(struct Picture *pic)
  458. {
  459.     struct UCopList *ucop;
  460.  
  461.     if (!pic->SHAMColors) return;    /* Not an SHAM picture, no work to do */
  462.  
  463.     if (ucop = AllocMem(sizeof(*ucop), MEMF_PUBLIC | MEMF_CLEAR) )
  464.     {
  465.         struct Screen *s = pic->Screen;
  466.         LONG i, j, step = (s->ViewPort.Modes&LACE) ? 2:1;
  467.         UWORD copx = GfxBase->ActiView->DxOffset + s->Width;
  468.         UWORD y0 = s->ViewPort.RasInfo->RyOffset;
  469.  
  470.         if (pic->Flags & PICF_DYNA) step = 1;
  471.  
  472.         for (i=1; i < (s->Height/step); ++i)
  473.         {
  474.             CWAIT(ucop, pic->Y0 + (i-1)*step, (UWORD)((copx>>1) % (UWORD)228))
  475.             for(j=1; j<16; ++j)
  476.                 CMOVE(ucop, custom.color[j], pic->SHAMColors[16*(y0+i)+j])
  477.         }
  478.         CEND(ucop)
  479. //        FreeVPortCopLists(&s->ViewPort);
  480.         s->ViewPort.UCopIns = ucop;
  481. //        pic->SHAMColors[16*y0] = pic->ColorTab[0];    /* Fix some weird SHAM pics */
  482.         LoadRGB4(&s->ViewPort, &pic->SHAMColors[16*y0], 16);
  483.     }
  484. }
  485.  
  486.  
  487. /****************************************************************************
  488. **    Free a picture (that is a window, screen and a custom BitMap)
  489. */
  490.  
  491. void ClosePicture(struct Picture *pic)
  492. {
  493.     if (pic->Window)
  494.     {
  495.         ScreenToBack(pic->Screen);
  496.         ClearPointer(pic->Window);
  497.         CloseWindow(pic->Window);
  498.         pic->Window = NULL;
  499.     }
  500.  
  501.     if (pic->Screen)
  502.     {
  503.         CloseScreen(pic->Screen);
  504.         pic->Screen = NULL;
  505.     }
  506.  
  507.     if (pic->BitMap)
  508.     {
  509.         MyFreeBitMap(pic->BitMap);
  510.         pic->BitMap = NULL;
  511.     }
  512.  
  513.     RemakeDisplay();    /* remake copper list to increase MEMF_LARGEST */
  514. }
  515.  
  516.  
  517. /****************************************************************************
  518. **    Get the view mode for a picture. If there is a CAMG chunk, we just
  519. **    return its contents. If there is none, we ask the graphics library for
  520. **    help. If it can't help us (<3.0), we calculate a view mode by hand.
  521. */
  522.  
  523. static ULONG GetBestViewMode(IFFL_HANDLE iff, struct IFFL_BMHD *bmhd)
  524. {
  525.     ULONG viewmode;
  526.  
  527.     /*
  528.     **    We don't want iff.library to give us a default viewmode if no
  529.     **    CAMG is present, so we must check first for a CAMG, and only
  530.     **    if it's there we can call IFFL_GetViewModes()
  531.     */
  532.     if (IFFL_FindChunk(iff, ID_CAMG) )
  533.     {
  534.         viewmode = IFFL_GetViewModes(iff);
  535. #ifdef VERBOSE
  536.         Printf("CAMG: $%08lx ", viewmode);
  537. #endif
  538.     }
  539.     else
  540.     {
  541.         viewmode = INVALID_ID;
  542.  
  543.         if (OSVERSION(39) )
  544.         {
  545.             viewmode = BestModeID(
  546.                             BIDTAG_NominalWidth,    bmhd->w,
  547.                             BIDTAG_NominalHeight,    bmhd->h,
  548.                             BIDTAG_DesiredWidth,    bmhd->w,
  549.                             BIDTAG_DesiredHeight,    bmhd->h,
  550.                             BIDTAG_Depth,            bmhd->nPlanes,
  551.  
  552. //                            BIDTAG_MonitorID,        monitorid,
  553.  
  554.                             monitorid ? BIDTAG_MonitorID : TAG_IGNORE,
  555.                                                     monitorid,
  556.                             TAG_DONE
  557.                         );
  558. #ifdef VERBOSE
  559.             Printf("BESTID: $%08lx ", viewmode);
  560. #endif
  561.         }
  562.     }
  563.  
  564.     /*
  565.     **    If we don't have a valid viewmode by now, let's handcraft it...
  566.     */
  567.     if (viewmode == INVALID_ID)
  568.     {
  569. #if 0
  570.         /*
  571.         **    $$$ This is for non-aga only!!! fix!!
  572.         */
  573.         viewmode = 0;
  574.         if((bmhd->nPlanes <=4) || (bmhd->nPlanes == 24))
  575.         {
  576.             if(bmhd->w > 400) viewmode |= HIRES_KEY;
  577.         }
  578.         else if(bmhd->nPlanes == 6) viewmode |= HAM_KEY;
  579.  
  580.         if(bmhd->h > 320) viewmode |= LORESLACE_KEY;
  581. #else
  582.         viewmode = monitorid;        // Test
  583. #endif
  584.  
  585. #ifdef VERBOSE
  586.         Printf("MY GUESS: $%08lx ", viewmode);
  587. #endif
  588.     }
  589.  
  590.     return viewmode;
  591. }
  592.  
  593.  
  594. /****************************************************************************
  595. **    Allocate a picture (Allocate custom BitMap, open screen and window)
  596. */
  597.  
  598. BOOL OpenPicture(struct Picture *pic)
  599. {
  600.     struct DimensionInfo    di;
  601.     struct IFFL_BMHD        *bmhd;
  602.     ULONG                    viewmode, overscan;
  603.     int                        xpos, ypos, width, height, depth;
  604.  
  605.     /*
  606.     **    If this picture was already loaded, free it.
  607.     */
  608.     ClosePicture(pic);
  609.     memset(pic, 0, sizeof(*pic));
  610.  
  611.  
  612.     /*
  613.     **    First, we get the BMHD chunk from the file. If there is none,
  614.     **    we show an error message and return.
  615.     */
  616.     if ( !(bmhd = IFFL_GetBMHD(ifffile)) )
  617.     {
  618.         PrintIFFError();
  619.         return FALSE;
  620.     }
  621.  
  622.     Printf("%ld x %ld x %ld ", bmhd->w, bmhd->h, bmhd->nPlanes);
  623.     Flush(Output());
  624.  
  625.  
  626.     /*
  627.     **    Get the viewmodes and its monitor dimension info, and calculate
  628.     **    the screen position, width and height. If the picture is larger
  629.     **    than the max overscan area, it is displayed with OSCAN_TEXT, and
  630.     **    can be scrolled with the mouse.
  631.     */
  632.     viewmode = GetBestViewMode(ifffile, bmhd);
  633.  
  634.     if (GetDisplayInfoData(NULL,(UBYTE *)&di, sizeof(di), DTAG_DIMS, viewmode) )
  635.     {
  636.         BOOL    scroll = FALSE;
  637.  
  638.         int maxwidth    = di.VideoOScan.MaxX - di.VideoOScan.MinX + 1;
  639.         int maxheight    = di.VideoOScan.MaxY - di.VideoOScan.MinY + 1;
  640.  
  641.         int stdwidth    = di.TxtOScan.MaxX - di.TxtOScan.MinX + 1;
  642.         int stdheight    = di.TxtOScan.MaxY - di.TxtOScan.MinY + 1;
  643.  
  644.         width            = SetBounds(bmhd->w, di.MinRasterWidth, maxwidth+XOSCAN);
  645.         height            = SetBounds(bmhd->h, stdheight, maxheight+YOSCAN);
  646.         depth            = SetBounds(bmhd->nPlanes, 1, di.MaxDepth);
  647.  
  648.         if (bmhd->w > (maxwidth+XOSCAN))    /* Too wide, scroll horizontally */
  649.         {
  650.             width    = stdwidth;
  651.             scroll    = TRUE;
  652.         }
  653.  
  654.         if (bmhd->h > (maxheight+YOSCAN))    /* Too high, scroll vertically */
  655.         {
  656.             height    = stdheight;
  657.             scroll    = TRUE;
  658.         }
  659.  
  660.         if (((bmhd->w > stdwidth) || (bmhd->h > stdheight)) && !scroll)
  661.         {
  662.             overscan    = OSCAN_VIDEO;
  663.         }
  664.         else overscan    = OSCAN_TEXT;
  665.  
  666.         pic->PicW    = bmhd->w;
  667.         pic->PicH    = bmhd->h;
  668.         pic->Y0        = SetBounds((height - bmhd->h) / 2, 0, height);
  669.  
  670.         if (!argv.NoCenterFlag)
  671.         {
  672.             xpos    = (stdwidth  - width)  / 2;
  673.             ypos    = (stdheight - height) / 2;
  674.         }
  675.         else
  676.         {
  677.             xpos = ypos = pic->Y0 = 0;
  678.         }
  679.  
  680. #ifdef VERBOSE
  681.         Printf("\nScr(%ld x %ld x %ld) Max(%ld x %ld x %ld) ",
  682.                     width, height, depth, maxwidth, maxheight, di.MaxDepth);
  683. #endif
  684.     }
  685.     else
  686.     {
  687.         switch (ModeNotAvailable(viewmode) )
  688.         {
  689.             case DI_AVAIL_NOCHIPS:
  690.                 Printf("You need a better chipset for view mode $%08lx\n", viewmode);
  691.                 break;
  692.  
  693.             case DI_AVAIL_NOMONITOR:
  694.                 Printf("The required monitor ($%08lx) is not available\n", viewmode);
  695.                 break;
  696.  
  697.             case  DI_AVAIL_NOTWITHGENLOCK:
  698.                 Printf("The monitor $%08lx does not support genlocks\n", viewmode);
  699.                 break;
  700.  
  701.             default:
  702.                 Printf("View mode $%08lx not available.\n", viewmode);
  703.                 break;
  704.         }
  705.  
  706.         return FALSE;
  707.     }
  708.  
  709.  
  710.     /*
  711.     **    Allocate the screen's bitmap
  712.     */
  713.     if (pic->BitMap = MyAllocBitMap(
  714.                 bmhd->nPlanes, MAX(bmhd->w, width), MAX(bmhd->h, height)) )
  715.     {
  716.         ULONG    oserror;
  717.  
  718.         pic->BitMap->Depth = depth;    /* Make OpenScreen() work */
  719.  
  720.         /*
  721.         **    Now open the screen
  722.         */
  723.         if (pic->Screen = OpenScreenTags(NULL,
  724.                 SA_Left,        xpos,
  725.                 SA_Top,            ypos,
  726.                 SA_Width,        width,
  727.                 SA_Height,        height,
  728.                 SA_Depth,        depth,
  729.                 SA_BitMap,        pic->BitMap,
  730.                 SA_Behind,        TRUE,
  731.                 SA_Quiet,        TRUE,
  732.                 SA_Type,        CUSTOMSCREEN,
  733.                 SA_DisplayID,    viewmode,
  734.                 SA_Overscan,    overscan,
  735.                 SA_ErrorCode,    &oserror,
  736.                 TAG_DONE
  737.             ))
  738.         {
  739.             UBYTE    *colortab;
  740.  
  741.             pic->BitMap->Depth = bmhd->nPlanes;        /* Undo cheat */
  742.  
  743.             /*
  744.             **    Create the color palette (read from CMAP chunk, if any)
  745.             */
  746.             if (bmhd->nPlanes == 24)
  747.             {
  748.                 /*
  749.                 **    If we have a 24bit true color picture, we calculate a
  750.                 **    "true color" palette and use the screen's most significant
  751.                 **    bitplanes for our reduced true color picture. This doesn't
  752.                 **    look perfect, but is FAST. Feel free to enhance this.
  753.                 */
  754.                 int greenbits, rbbits, i;
  755.  
  756. //                depth = 3;
  757.  
  758.                 greenbits    = CreateTrueColorPalette(pic->Palette, depth);
  759.                 rbbits        = (depth-greenbits)/2;
  760.  
  761.                 /*
  762.                 **    Rearrange the bitplane pointers of our screen.
  763.                 **    This is not quite legal, I suppose (but OK for PD :-))
  764.                 */
  765.                 for (i=0; i<greenbits; ++i)
  766.                 {
  767.                     pic->Screen->BitMap.Planes[i] =
  768.                                             pic->BitMap->Planes[16-greenbits+i];
  769.                 }
  770.  
  771.                 for (i=0; i < rbbits; ++i)
  772.                 {
  773.                     pic->Screen->BitMap.Planes[greenbits+i] =
  774.                                             pic->BitMap->Planes[8-rbbits+i];
  775.  
  776.                     pic->Screen->BitMap.Planes[greenbits+rbbits+i] =
  777.                                             pic->BitMap->Planes[24-rbbits+i];
  778.                 }
  779.  
  780.                 pic->ColorCount = 1 << depth;
  781.             }
  782.             else if (colortab = IFFL_FindChunk(ifffile, ID_CMAP) )
  783.             {
  784.                 pic->ColorCount =
  785.                     SetBounds(*(ULONG *)(colortab+4) / 3, 0, MAXCOLORS);
  786.  
  787.                 CopyMem(colortab+8, pic->Palette,
  788.                                     pic->ColorCount * sizeof(RGBColor));
  789.             }
  790.             else
  791.             {
  792.                 /*
  793.                 **    Use default colors for pictures without a CMAP
  794.                 */
  795.                 static RGBColor white = { 0xEE, 0xCC, 0xAA };
  796.                 pic->ColorCount = 2;
  797.                 pic->Palette[0] = white;
  798. //                pic->Palette[1] = black;
  799.             }
  800.  
  801.             LoadRGB8(&pic->Screen->ViewPort, pic->Palette, pic->ColorCount);
  802.  
  803.  
  804.             /*
  805.             **    To get our intuimessages, we open a window in the screen
  806.             */
  807.             if (pic->Window = OpenWindowTags(NULL,
  808.                     WA_Flags,            WFLG_BACKDROP | WFLG_BORDERLESS
  809.                                         | WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH
  810.                                         | WFLG_NOCAREREFRESH | WFLG_REPORTMOUSE
  811.                                         | WFLG_RMBTRAP,
  812.                     WA_IDCMP,             IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE
  813.                                         | IDCMP_DELTAMOVE | IDCMP_VANILLAKEY,
  814.                     WA_CustomScreen,    pic->Screen,
  815.                     TAG_DONE
  816.                 ))
  817.             {
  818.                 /*
  819.                 **    Clear the mouse pointer if desired
  820.                 */
  821.                 if( !argv.PointerFlag)
  822.                     SetPointer(pic->Window, emptysprite, 1L, 16L, 0L, 0L);
  823.  
  824.                 return TRUE;
  825.             }
  826.         }
  827.         else switch (oserror)            /* OpenScreenTags() failed */
  828.         {
  829.             case OSERR_NOMONITOR:
  830.                 PutStr("Monitor not available.\n");
  831.                 break;
  832.  
  833.             case OSERR_NOCHIPS:
  834.                 PutStr("You need newer custom chips.\n");
  835.                 break;
  836.  
  837.             case OSERR_NOMEM:
  838.                 PutStr("Not enough free main memory.\n");
  839.                 break;
  840.  
  841.             case OSERR_NOCHIPMEM:
  842.                 PutStr("Not enough free chip mempry.\n");
  843.                 break;
  844.  
  845.             case OSERR_UNKNOWNMODE:
  846.                 PutStr("Bad screen mode.\n");
  847.                 break;
  848.  
  849.             case OSERR_TOODEEP:
  850.                 PutStr("Too many colors requested.\n");
  851.                 break;
  852.  
  853.             case OSERR_NOTAVAILABLE:
  854.                 PutStr("Can't open screen.\n");
  855.                 break;
  856.  
  857.             default:
  858.                 PutStr("You're completely lost.\n");
  859.                 break;
  860.         }
  861.     }
  862.     else PutStr("Not enough memory\n");
  863.  
  864.     ClosePicture(pic);
  865.     return FALSE;
  866. }
  867.  
  868.  
  869. /****************************************************************************
  870. **    That's the big one! Load and display a picture, handle mouse movement
  871. **    and other input events.
  872. **    Returns FALSE if user presses the RMB (abort), else returns TRUE
  873. */
  874.  
  875. BOOL ShowPicture(char *name)
  876. {
  877.     BOOL cont = TRUE;
  878.  
  879.     /*
  880.     **    Skip icon files
  881.     */
  882.     {
  883.         int len = strlen(name);
  884.         if (len >= 5)
  885.         {
  886.             if ( !Stricmp(name + len-5, ".info") )
  887.                 return TRUE;
  888.         }
  889.     }
  890.  
  891.     Printf("%s ... ", name);
  892.     Flush(Output());
  893.  
  894.  
  895.     /*
  896.     **    Load the IFF file into memory. If a file was already loaded, free
  897.     **    its memory first.
  898.     */
  899.     if(ifffile) IFFL_CloseIFF(ifffile);
  900.  
  901.     if ( !(ifffile = IFFL_OpenIFF(name, IFFL_MODE_READ)) )
  902.     {
  903.         PrintIFFError();
  904.         return TRUE;
  905.     }
  906.  
  907.     if ( *(((ULONG *)ifffile)+2) != ID_ILBM)
  908.     {
  909.         PutStr("Not an ILBM picture\n");
  910.         return TRUE;
  911.     }
  912.  
  913. retry:
  914.     if (OpenPicture(&pic1) )
  915.     {
  916.         if (IFFL_DecodePic(ifffile, pic1.BitMap) )
  917.         {
  918.             struct SHAMChunk    *sham;
  919.             LONG                i;
  920.             int                    xoff = 0, yoff = 0;
  921.             int                    maxx0 = pic1.PicW - pic1.Screen->Width;
  922.             int                    maxy0 = pic1.PicH - pic1.Screen->Height;
  923.  
  924.             /*
  925.             **    In 2.0 there's this RasInfo scrolling bug, it's fixed
  926.             **    for 3.0, so we'll make an explicit version check, and
  927.             **    a workaround for the bug.
  928.             */
  929.             if (pic1.Screen->ViewPort.Modes & HIRES)
  930.             {
  931.                 if(    (GfxBase->LibNode.lib_Version >= 36)
  932.                     &&    (GfxBase->LibNode.lib_Version <= 38) )
  933.                  maxx0 >>= 1;
  934.             }
  935.  
  936.  
  937.             /*
  938.             **    If the picture is not as high as the screen, we have to
  939.             **    move it down so it will be centered.
  940.             */
  941.             if (pic1.Y0)
  942.             {
  943. //                Printf("ScrollRaster(rp,0,%ld,0,0,%ld,%ld)\n",-pic1.Y0,pic1.PicW-1,pic1.PicH-1);
  944.                 ScrollRaster(&pic1.Screen->RastPort,
  945.                                     0, -pic1.Y0, 0, 0, pic1.PicW-1, pic1.PicH+pic1.Y0-1);
  946.             }
  947.  
  948.  
  949.             /*
  950.             **    If an SHAM or DYNA chunk is found, build the appropriate
  951.             **    copper list to display the picture. This may not be supported
  952.             **    in future versions.
  953.             */
  954.             if (sham = IFFL_FindChunk(ifffile, ID_SHAM) )
  955.             {
  956.                 Printf("SHAM ");
  957.                 if (sham->Version == 0)
  958.                 {
  959.                     pic1.SHAMColors = sham->Colors;
  960.                 }
  961.                 else Printf("Unsupported mode: %ld ", (LONG)sham->Version);
  962.  
  963.                 MakeSHAMCopList(&pic1);
  964.             }
  965.  
  966.             if (sham = IFFL_FindChunk(ifffile, ID_CTBL) )
  967.             {
  968.                 Printf("DYNA ");
  969.                 pic1.SHAMColors = &sham->Version;    /* DYNA has no version */
  970.                 pic1.Flags |= PICF_DYNA;
  971.                 MakeSHAMCopList(&pic1);
  972.             }
  973.  
  974.             Flush(Output());
  975.  
  976.  
  977.             /*
  978.             **    Display the picture, and close a possible old one
  979.             */
  980.             ScreenToFront(pic1.Screen);
  981.             ClosePicture(&pic2);
  982.  
  983.  
  984.             /*
  985.             **    And now for the event loop ...
  986.             */
  987.             for (i = 0; i < delay; ++i)
  988.             {
  989.                 struct IntuiMessage *msg;
  990.  
  991.                 WaitTOF();
  992.                 while (msg = (struct IntuiMessage *)GetMsg(pic1.Window->UserPort) )
  993.                 {
  994. newmsg:                switch(msg->Class)
  995.                     {
  996.                     case IDCMP_MOUSEMOVE:
  997.  
  998.                         xoff += msg->MouseX;
  999.                         yoff += msg->MouseY;
  1000.                         xoff  = SetBounds(xoff, 0, maxx0);
  1001.                         yoff  = SetBounds(yoff, 0, maxy0);
  1002.  
  1003.                         pic1.Screen->ViewPort.RasInfo->RxOffset = xoff;
  1004.                         pic1.Screen->ViewPort.RasInfo->RyOffset = yoff;
  1005.  
  1006.                         /*
  1007.                         **    If there is an SHAM copper list, we must
  1008.                         **    update it if the user scrolled the picture.
  1009.                         **    This is quite slow, so we collect all mouse
  1010.                         **    movement messages during this time.
  1011.                         */
  1012.                         if (pic1.SHAMColors)
  1013.                         {
  1014.                             struct IntuiMessage *m2;
  1015.  
  1016.                             MakeSHAMCopList(&pic1);
  1017.                             while (m2 = (struct IntuiMessage *)GetMsg(pic1.Window->UserPort) )
  1018.                             {
  1019.                                 ReplyMsg(msg); msg = m2;
  1020.  
  1021.                                 if(msg->Class == IDCMP_MOUSEMOVE)
  1022.                                 {
  1023.                                     xoff += msg->MouseX;
  1024.                                     yoff += msg->MouseY;
  1025.                                 }
  1026.                                 else goto newmsg;
  1027.                             }
  1028.                         }
  1029.  
  1030.                         /*
  1031.                         **    Now make the changes visible. Under V39 we
  1032.                         **    use the updated ScrollVPort() routine.
  1033.                         */
  1034. #if 0
  1035.                         if (OSVERSION(39) )
  1036.                         {
  1037.                             ScrollVPort(&pic1.Screen->ViewPort);
  1038.                         }
  1039.                         else
  1040. #endif
  1041.                         {
  1042.                             MakeScreen(pic1.Screen);
  1043.                             RethinkDisplay();
  1044.                         }
  1045.                         break;
  1046.  
  1047.                     case IDCMP_VANILLAKEY:
  1048.                         if (msg->Code == 'c')
  1049.                         {
  1050.                             if (argv.Command)
  1051.                             {
  1052.                                 char buf[200];
  1053.                                 sprintf(buf, argv.Command, name, name);
  1054.                                 Execute(buf, NULL, Output());
  1055.                             }
  1056.                         }
  1057.                         break;
  1058.  
  1059.                     case IDCMP_MOUSEBUTTONS:
  1060.                         if (!argv.NoBreakFlag)
  1061.                         {
  1062.                             if (msg->Code == MENUDOWN)        goto usrbreak;
  1063.                             if (msg->Code == SELECTDOWN)    goto showend;
  1064.                         }
  1065.                         break;
  1066.                     }
  1067.  
  1068.                     ReplyMsg(msg);
  1069.                 }
  1070.  
  1071.                 /*
  1072.                 **    If the user hits Ctrl-C we quit, if not NOBREAK
  1073.                 */
  1074.                 if (!argv.NoBreakFlag)
  1075.                 {
  1076.                     if (CheckSignal(SIGBREAKF_CTRL_C) )
  1077.                     {
  1078. usrbreak:                PutStr("***BREAK\n");
  1079.                         cont = FALSE;
  1080.                         goto showend2;
  1081.                     }
  1082.                 }
  1083.             }
  1084.  
  1085. showend:
  1086.             PutStr("- Done\n");
  1087.  
  1088. showend2:
  1089.             pic2 = pic1;
  1090.             memset(&pic1, 0, sizeof(pic1) );
  1091.         }
  1092.         else
  1093.         {
  1094.             ClosePicture(&pic1);
  1095.             PrintIFFError();
  1096.         }
  1097.     }
  1098.     else if(pic2.Window)
  1099.     {
  1100.         ClosePicture(&pic2);
  1101.         goto retry;
  1102.     }
  1103.  
  1104.     return cont;
  1105. }
  1106.  
  1107.  
  1108. /****************************************************************************
  1109. **    Expand a pattern and call ShowPicture() for each matching file.
  1110. **    Rreturn FALSE if the user presses ^C, or if ShowPicture() returned FALSE.
  1111. */
  1112.  
  1113. BOOL ShowPattern(char *pathname)
  1114. {
  1115.     char buf[256];
  1116.     BPTR file;
  1117.     BOOL cont = TRUE;
  1118.  
  1119.     /*
  1120.     **    Check if the supplied pathname contains any wildcards. In this
  1121.     **    case (ParsePattern() returns TRUE) we scan the directory.
  1122.     **    If no wildcards are found, we just pass along the name to
  1123.     **    ShowPicture(), if it is not the name of a directory.
  1124.     */
  1125.     if (ParsePatternNoCase(pathname, buf, sizeof(buf)) )
  1126.     {
  1127.         struct
  1128.         {
  1129.             struct AnchorPath APath;
  1130.             char   FullPath[255];        /* cheap way to extend ap_Buf[] */
  1131.         } *myanchor;
  1132.  
  1133. iswild:
  1134.         if (myanchor = AllocVec(sizeof(*myanchor), MEMF_PUBLIC | MEMF_CLEAR) )
  1135.         {
  1136.             BOOL showit = TRUE;
  1137.             LONG error;
  1138.  
  1139.             myanchor->APath.ap_Strlen        = sizeof(myanchor->FullPath);
  1140.             myanchor->APath.ap_Flags        = APF_DOWILD;
  1141.             myanchor->APath.ap_BreakBits    = SIGBREAKF_CTRL_C;
  1142.  
  1143.             error = MatchFirst(pathname, myanchor);
  1144.  
  1145.             while (!error)
  1146.             {
  1147.                 if (CheckSignal(SIGBREAKF_CTRL_E) )
  1148.                 {
  1149.                     PutStr("***DIR BREAK\n"); showit=FALSE;
  1150.                     /* myanchor->APath.ap_Flags &= ~APF_DODIR; */
  1151.                 }
  1152.  
  1153.                 if(myanchor->APath.ap_Info.fib_DirEntryType >= 0)    /* Dir */
  1154.                 {
  1155.                     if (argv.AllFlag)
  1156.                     {
  1157.                         if ( !(myanchor->APath.ap_Flags & APF_DIDDIR) )
  1158.                         {
  1159.                             myanchor->APath.ap_Flags |= APF_DODIR;
  1160.                             showit = TRUE;
  1161.                         }
  1162.                         myanchor->APath.ap_Flags &= ~APF_DIDDIR;
  1163.                     }
  1164.                 }
  1165.                 else if(showit)
  1166.                 {
  1167.                     if (!ShowPicture(myanchor->APath.ap_Buf) )
  1168.                     {
  1169.                         cont = FALSE;
  1170.                         break;
  1171.                     }
  1172.                 }
  1173.                 error = MatchNext(myanchor);
  1174.             }
  1175.  
  1176.             MatchEnd(myanchor);
  1177.  
  1178.  
  1179.             /*
  1180.             **    Find out why the loop terminated
  1181.             */
  1182.             switch(error)
  1183.             {
  1184.                 case 0:
  1185.                     break;
  1186.  
  1187.                 case ERROR_BREAK:
  1188.                     PutStr("***BREAK\n");
  1189.                     cont = FALSE;
  1190.                     break;
  1191.  
  1192.                 case ERROR_OBJECT_NOT_FOUND:
  1193.                     PutStr("File not found\n");
  1194.                     cont = FALSE;
  1195.                     break;
  1196.  
  1197.                 case ERROR_BUFFER_OVERFLOW:
  1198.                     PutStr("Path too long\n");
  1199.                     break;
  1200.  
  1201.                 case ERROR_NO_MORE_ENTRIES:        /* Normal termination */
  1202.                     break;
  1203.  
  1204.                 default:
  1205.                     PrintFault(error, "");
  1206.                     break;
  1207.             }
  1208.  
  1209.             FreeVec(myanchor);
  1210.         }
  1211.         else PutStr("No memory for anchor\n");
  1212.     }
  1213.     else if (file = Open(pathname, MODE_OLDFILE) )    /* Just one file ? */
  1214.     {
  1215.         Close(file);
  1216.         return ShowPicture(pathname);
  1217.     }
  1218.     else    /* No wildcards, and not a file: it's a device or a directory */
  1219.     {
  1220.         strcpy(buf, pathname);
  1221.         AddPart(pathname=buf, "#?", sizeof(buf));
  1222.         goto iswild;                /* Not really elegant, but it works */
  1223.     }
  1224.  
  1225.     return cont;
  1226. }
  1227.  
  1228.  
  1229. /****************************************************************************
  1230. **    Started without arguments: create or delete our appicon
  1231. */
  1232.  
  1233. void AppIconStuff(void)
  1234. {
  1235.     struct MsgPort        *msgport;
  1236.       struct AppIcon        *ai;
  1237.     struct AppMessage    *amsg;
  1238.  
  1239.     if (msgport = FindPort(APPICONPORTNAME) )            /* Already running ? */
  1240.     {
  1241.         Signal(msgport->mp_SigTask, SIGBREAKF_CTRL_C);    /* Yes ---> Kill it */
  1242.     }    
  1243.     else if(msgport = CreateMsgPort() ) 
  1244.     {
  1245.         struct DiskObject    *appdobj = NULL;
  1246.         char                *tooltype;
  1247.  
  1248.         msgport->mp_Node.ln_Name = APPICONPORTNAME;
  1249.         AddPort(msgport);
  1250.  
  1251.         /*
  1252.         **    If an "ICON" tooltype is specified, we use this as the
  1253.         **    appicon for ShowIFF. Default is ShowIFF's own icon image.
  1254.         */
  1255.         if (tooltype = FindToolType(dobj->do_ToolTypes, ICONTOOLTYPE) )
  1256.             appdobj = GetDiskObject(tooltype);
  1257.  
  1258.         if (appdobj == NULL) appdobj = dobj;
  1259.  
  1260.         /*
  1261.         **    Position of the appicon can be specified with "ICON[XY]POS"
  1262.         */
  1263.         if (tooltype = FindToolType(dobj->do_ToolTypes, XPOSTOOLTYPE) )
  1264.             appdobj->do_CurrentX = GetNumber(tooltype);
  1265.         else
  1266.             appdobj->do_CurrentX = NO_ICON_POSITION;
  1267.  
  1268.         if (tooltype = FindToolType(dobj->do_ToolTypes, YPOSTOOLTYPE) )
  1269.             appdobj->do_CurrentY = GetNumber(tooltype);
  1270.         else
  1271.             appdobj->do_CurrentY = NO_ICON_POSITION;
  1272.  
  1273.         /*
  1274.         **    The appicon's name is set with "ICONNAME"
  1275.         */
  1276.         if ( !(tooltype = FindToolType(dobj->do_ToolTypes, ICONNAMETOOLTYPE)) )
  1277.             tooltype = DEFAULTAPPICONNAME;
  1278.  
  1279.         /*
  1280.         **    Add our appicon
  1281.         */
  1282.         if (ai = AddAppIconA(0, 0, tooltype, msgport, NULL, appdobj, NULL) ) 
  1283.         {
  1284.             while ( !(Wait(1L << msgport->mp_SigBit | SIGBREAKF_CTRL_C)
  1285.                          & SIGBREAKF_CTRL_C) )
  1286.             {
  1287.                 if (wbwindow = Open(WindowTitle, MODE_OLDFILE) )
  1288.                 {
  1289.                     oldcos = SelectOutput(wbwindow);
  1290.                 }
  1291.  
  1292.                 while(amsg = (struct AppMessage *)GetMsg(msgport) )
  1293.                 {
  1294.                     struct WBArg    *arg = amsg->am_ArgList;
  1295.                     int                i, cont = TRUE;
  1296.  
  1297.                       for(i=0; (i < amsg->am_NumArgs) && cont; i++,arg++)
  1298.                       {
  1299.                         BPTR oldcd = 0;
  1300.                         if(arg->wa_Lock)    oldcd = CurrentDir(arg->wa_Lock);
  1301.                         else                DisplayBeep(NULL);
  1302.  
  1303.                         cont = ShowPattern(arg->wa_Name && *arg->wa_Name
  1304.                                                 ? (STRPTR)arg->wa_Name : "#?");
  1305.                         if(oldcd) CurrentDir(oldcd);
  1306.                     }
  1307.                     ReplyMsg(amsg);
  1308.                 }
  1309.  
  1310.                 ClosePicture(&pic2);         /* Close last screen */
  1311.  
  1312.  
  1313.                 if(wbwindow)
  1314.                 {
  1315.                     WaitForChar(wbwindow, 2L<<20);        /* Wait 2 seconds */
  1316.                     SelectOutput(oldcos);
  1317.                     oldcos = 0;
  1318.                     Close(wbwindow);
  1319.                     wbwindow = NULL;
  1320.                     SetSignal(0, SIGBREAKF_CTRL_C);        /* Clear break sig */
  1321.                 }
  1322.             }
  1323.             RemoveAppIcon(ai);
  1324.         }
  1325.  
  1326.         if(appdobj != dobj) FreeDiskObject(appdobj);
  1327.  
  1328.         /*
  1329.         **    Make sure there are no more messages pending
  1330.         */
  1331.         while (amsg = (struct AppMessage *)GetMsg(msgport) )
  1332.             ReplyMsg(amsg);
  1333.  
  1334.         RemPort(msgport);
  1335.         DeleteMsgPort(msgport);
  1336.     }
  1337. }
  1338.  
  1339.  
  1340. /****************************************************************************
  1341. **    The entry point, called from ArgsStartup20.o
  1342. */
  1343.  
  1344. LONG Main(struct WBStartup *startup, LONG arglen)
  1345. {
  1346.     #define argline ((char *)startup)
  1347.  
  1348.     /*
  1349.     **    Open all needed libraries
  1350.     */
  1351.     if ( !(UtilityBase = OpenLibrary(UTILITYNAME, 36L)) )
  1352.         goto quit;
  1353.  
  1354.     if ( !(GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME, 36L)) )
  1355.         goto quit;
  1356.  
  1357.     if ( !(IntuitionBase = (void *)OpenLibrary("intuition.library", 36L)) )
  1358.         goto quit;
  1359.  
  1360.        if ( !(IconBase = OpenLibrary(ICONNAME, 36L)) )
  1361.         goto quit;
  1362.  
  1363.     if ( !(WorkbenchBase = OpenLibrary(WORKBENCH_NAME, 36L)) )
  1364.         goto quit;
  1365.  
  1366.     if ( !(IFFBase = OpenLibrary(IFFNAME, 19L)) )
  1367.         goto quit;
  1368.  
  1369.     if (IFFBase->lib_Version < IFFVERSION)
  1370.         PutStr("WARNING: you have an old version of iff.library\n");
  1371.  
  1372.  
  1373.     /*
  1374.     **    Get args from WB or CLI as appropriate
  1375.     */
  1376.     if (arglen)        /* From CLI */
  1377.     {
  1378.         if (*argline != '\n')
  1379.         {
  1380.             if (argv.DelayPtr)
  1381.                 delay = *argv.DelayPtr * SysBase->VBlankFrequency + 1;
  1382.  
  1383.             if (argv.Monitor)
  1384.                 monitorid = GetNumber(argv.Monitor);
  1385.  
  1386.             do
  1387.             {
  1388.                 char **pattern = argv.Patterns;
  1389.  
  1390.                 if (*pattern)
  1391.                 {
  1392.                     while (*pattern)
  1393.                         if (!ShowPattern(*pattern++) )
  1394.                             goto done;
  1395.                 }
  1396.                 else ShowPattern("#?");
  1397.  
  1398.             } while (argv.LoopFlag);
  1399. done:
  1400.             PutStr("All done.\n");
  1401.         }
  1402.         else
  1403.         {
  1404.             PutStr(VersionString+7);
  1405.             PutStr(CLI_Help);
  1406.         }
  1407.     }
  1408.     else    /* Called from Workbench */
  1409.     {
  1410.         /*
  1411.         **    Set defaults for Workbench
  1412.         */
  1413.         argv.AllFlag        = TRUE;
  1414. //        argv.LoopFlag        = FALSE;
  1415. //        argv.NoBreakFlag    = FALSE;
  1416. //        argv.NoOverscanFlag    = FALSE;
  1417.  
  1418.         if (dobj = GetDiskObject(startup->sm_ArgList->wa_Name))
  1419.         {
  1420.             char *tooltype;
  1421.  
  1422. #if 0
  1423.             if (tooltype = FindToolType(dobj->do_ToolTypes, OPTIONSTOOLTYPE) )
  1424.             {
  1425.                 GADS(tooltype, strlen(tooltype), NULL, argv, CLI_Template);
  1426.                 if (argv.DelayPtr)
  1427.                     delay = *argv.DelayPtr * SysBase->VBlankFrequency + 1;
  1428.             }
  1429. #endif
  1430.  
  1431.             if (tooltype = FindToolType(dobj->do_ToolTypes, "MONITOR") )
  1432.                 monitorid = GetNumber(tooltype);
  1433.         }
  1434.  
  1435.         if (startup->sm_NumArgs > 1)    /* Started with some arguments */
  1436.         {
  1437.             struct WBArg    *arg = startup->sm_ArgList;
  1438.             int                i;
  1439.  
  1440.             /*
  1441.             **    Open our output window
  1442.             */
  1443.             if (wbwindow = Open(WindowTitle, MODE_OLDFILE) )
  1444.                 oldcos = SelectOutput(wbwindow);
  1445.  
  1446.             for (i=1; i<startup->sm_NumArgs; ++i)
  1447.             {
  1448.                 arg++;
  1449.                 if (arg->wa_Lock)    CurrentDir(arg->wa_Lock);
  1450.                 else                PutStr("Can't lock directory\n");
  1451.  
  1452.                 if (arg->wa_Name && *arg->wa_Name)
  1453.                 {
  1454.                     if (!ShowPattern(arg->wa_Name) )
  1455.                         break;
  1456.                 }
  1457.                 else ShowPattern("#?");
  1458.             }
  1459.  
  1460.             PutStr("All done.\n");
  1461.         }
  1462.         else    /* no arguments, just clicked */
  1463.         {
  1464.             AppIconStuff();
  1465.         }
  1466.     }
  1467.  
  1468.  
  1469.     /*
  1470.     **    Cleanup
  1471.     */
  1472. quit:
  1473.     ClosePicture(&pic1);
  1474.     ClosePicture(&pic2);
  1475.  
  1476.     if(ifffile) IFFL_CloseIFF(ifffile);
  1477.  
  1478.     if (dobj)
  1479.     {
  1480.         FreeDiskObject(dobj);
  1481. //        dobj = NULL;
  1482.     }
  1483.  
  1484.     if(wbwindow)
  1485.     {
  1486.         WaitForChar(wbwindow, 3L<<20);    /* Wait 3 seconds */
  1487.         Close(wbwindow);
  1488. //        wbwindow = 0;
  1489.     }
  1490.  
  1491.     if (oldcos)
  1492.     {
  1493.         SelectOutput(oldcos);
  1494. //        oldcos = 0;
  1495.     }
  1496.  
  1497.     CloseLibrary(IFFBase);
  1498.     CloseLibrary(WorkbenchBase);
  1499.     CloseLibrary(IconBase);
  1500.     CloseLibrary(IntuitionBase);
  1501.     CloseLibrary(GfxBase);
  1502.     CloseLibrary(UtilityBase);
  1503.  
  1504.     return RETURN_OK;
  1505. }
  1506.